﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ChainAnalises.Classes.DivizionToAccords.Criteria;
using ChainAnalises.Classes.IntervalAnalysis;
using Segmentator.IntegrityThroughInterval;
using Segmentator.Interfaces;

namespace Segmentator.Dividers
{
    class GurovRodionov: Algorithm
    {
        public static readonly string NAME = "GurovRodionov";
        /// <summary>
        /// Загружает данные для обработки 
        /// </summary>
        /// <param name="data"></param>
        public override void LoadData(IDataLoader data)
        {
            Data.ThresholdLeft = data.GetThresholdLeft();
            Data.ThresholdRight = data.GetThresholdRight();
            Data.ThresholdStep = data.GetThresholdStep();
            Data.ChainName = data.GetChainName();
            Data.IsSavingResults = data.IsSavingResults();
            Data.Sequence = data.GetSequence();
            Data.Precision = data.GetPrecision();
            Data.LengthStartWindow = data.GetLengthStartWindow();
            Data.AmountStartAlgorithm = data.GetAmountStartAlgorithm();
            Data.BalanceFactor = data.GetBalanceFactor();
        }

        /// <summary>
        /// Выгружает результаты сегментации
        /// </summary>
        public override CalculatorResults UpLoadData()
        {
            return new CalculatorResults(new Chain(Data.Sequence), ConvolutedChain, Alphabet, Threshold);
        }

        /// <summary>
        /// Сегментирует выбранную знаковую последовательность с учетом принятых параметров
        /// </summary>
        public override void Slot()
        {
            ThresholdVariator thresholdVariator = new DichotomyThreshold(Data.ThresholdLeft, Data.ThresholdRight);
            Dictionary<double, Divider> MinSymmDivider = new Dictionary<double, Divider>();
            Divider _Divider;

            for (int d = 0; d < Data.AmountStartAlgorithm; d++)
            {
                _Divider = new Divider(new Chain(Data.Sequence.ToUpper()), (Data.BalanceFactor / 100), Data.LengthStartWindow, _linkUp, Method.Convoluted, thresholdVariator.next(0), Data.Precision);                
                _Divider.Divizion_with_inspection();              
                searchMinSymmetry(_Divider, MinSymmDivider);
            }

            _Divider = GetDivider(MinSymmDivider);
            ConvolutedChain = _Divider.divided_chain;
            Alphabet = _Divider.full_alphabet;
            Threshold = _Divider.best_level;
        }

        /**
       * Рассчитывает симметрию распределения интервалов
       * сохраняет, после чего ищет минимальную симметрию из всех найденых ранее
       */
        private void searchMinSymmetry(Divider divider, Dictionary<double, Divider> map)
        {
            double value = 0;
            SplitByInterval spliter = new SplitByInterval();
            UMChainCapacity min = new UMChainCapacity();
            value = min.Min(spliter.split(divider.divided_chain.Building).exchange()); // ужас, передалать
            if (!map.ContainsKey(value)) map.Add(value, divider);
        }

        /// <summary>
        /// Возвращает сегментатор с минимальным значением симметрии строя цепи
        /// </summary>
        /// <param name="map"></param>
        /// <returns></returns>
        private Divider GetDivider(Dictionary<double, Divider> map)
        {
            double min = 100000000000000000000000000000.0;
            foreach (double kvp in map.Keys) if (kvp < min) min = kvp;
            return map[min];
        }
    }
}
